/**
 * @author Maria Adriana Vidigal de Lima
 *
 * We want to build a hashtable from the information stored in the
 * keyTree, after the validation from scratch. This hashtable will be
 * useful to consult when updates are proposed.
 */
package main;

import java.io.StringReader;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Vector;

import org.apache.xerces.parsers.SAXParser;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.DefaultHandler;

public class KeyTreeUpd extends DefaultHandler
{	
	private Hashtable<String, Hashtable<IndContext, Vector<TargetUpd>>> htKeyTree;
	private Hashtable<IndContext, Vector<TargetUpd>> htContext;
	private TargetUpd tUpd;  
	private Vector<TargetUpd> targetList;
	private boolean targetFlag;	
	private boolean keyTreeLocalVal = false; // to be used when we are parsing for local validation
	private String newIns; // also used in the local validation
	
	public KeyTreeUpd(){}
		
	public Hashtable<String, Hashtable<IndContext, Vector<TargetUpd>>> parseKeyTree (String fileKeyTree)
	{
		SAXParser splocal = new SAXParser();
		InputSource source = new InputSource(fileKeyTree);
		splocal.setContentHandler(this);
		try 
		{
			 splocal.parse(source);
			 return (htKeyTree);
		}
		catch (Exception e)
		{
			System.out.println("Parse Error: "+e);
		}
		
		return (new Hashtable<String, Hashtable<IndContext, Vector<TargetUpd>>>());
	}

	public Hashtable<String, Hashtable<IndContext, Vector<TargetUpd>>> parseKeyTreeContext (String keyTree, String nIns)
	{
		SAXParser splocal = new SAXParser();
	
		InputSource source = new InputSource(new StringReader(keyTree));
		splocal.setContentHandler(this);
		
		try
		{
			 //System.out.println("Before parsing Context entry");
			 keyTreeLocalVal = true;
			 newIns = nIns;
			 splocal.parse(source);
			 return (htKeyTree);
		}
		catch (Exception e)
		{
			System.out.println("Parse Error: "+e);
		}
		
		return (new Hashtable<String, Hashtable<IndContext, Vector<TargetUpd>>>());
	}
		
	public void startDocument()
	{
		htKeyTree = new Hashtable<String, Hashtable<IndContext, Vector<TargetUpd>>>();
	}

    public void startElement(String namespaceURI, String localName,
                             String rawName, Attributes attrs)
    {
		targetFlag=false;                     	          
		System.out.println("start element: "+rawName);                    	
		//Treatment for elements that are "Key"
        
		if (rawName.equals("Key"))
        {
			System.out.println("Trata elementos chaves");
			htContext = new Hashtable<IndContext, Vector<TargetUpd>>();
			if (attrs != null)
			{
				int len = attrs.getLength();
				for (int i=0; i<len; i++)
				{ 
					String sa = attrs.getQName(i);
					if (sa.equals("name"))
					{
					    String sb = (String) attrs.getValue(i);
					    htKeyTree.put(sb,htContext);
					}    
				}
			}		
        }
        else 
        { 
        	System.out.println("Trata elementos de context");
            //Treatment for elements that are "Context"
	     	if (rawName.equals("Context"))
	     	{
		    	targetList = new Vector<TargetUpd>();
			    if (attrs != null)
			    {
				    int len = attrs.getLength();
					for (int i=0; i<len; i++)
					{ 
				    	String sa = attrs.getQName(i);
				    	if (sa.equals("pos"))
				    	{
							String sb = (String) attrs.getValue(i);
							IndContext indCon = new IndContext(sb,sb,"0");
							htContext.put(indCon, targetList);
						}    
					}
				}					
			}
            else
            {    
            	System.out.println("elementos do target");
				//Treatment for elements that are "Target"
				if (rawName.equals("Target"))
				{
					tUpd = new TargetUpd();
					if (attrs != null)
					{
						int len = attrs.getLength();
						for (int i=0; i<len; i++)
						{ 
			 				String sa = attrs.getQName(i);
							if (sa.equals("pos"))
							{
								String sb = (String) attrs.getValue(i);
								tUpd.setPosition(sb);
							}  
							if (sa.equals("refCount"))
							{
								String sb = (String) attrs.getValue(i);
								tUpd.setRefCount(sb);
							}   
							
							tUpd.setDuplic("no");
							tUpd.setDelete("no");
							tUpd.setConfirm("yes");
							
							if (keyTreeLocalVal == false)
								tUpd.setNewInsertion("0");
							else
								tUpd.setNewInsertion(newIns);
							tUpd.setNewPos(tUpd.getPosition());																				   										  
						}	
					}		
				}
				else if (!rawName.equals("KeyTree"))
					targetFlag = true;
			}				
        }
    }

	public void characters(char ch[], int start, int length)
	{
		String str = new String(ch, start, length);
		
		if ((targetFlag == true) && (str.length()>0))
		{
		    tUpd.getValues().add(str);
		}  
		  
	}
	
	public void endElement(String namespaceURI, String localName, String rawName)
	{	
		targetFlag=false;  
		
		if (rawName.equals("Target"))
		{
			targetList.add(tUpd);
		}				
	}

    //Function to display the attribute htKeyTree, the hashtable with all
    //the information contained in the KeyTree
	public void displayHashKT()
	{
	   String keyName;
	   IndContext indCont;
	   Hashtable<IndContext, Vector<TargetUpd>> contextKey;
	   TargetUpd tUpd;
	   
	   for(Iterator<String> i = htKeyTree.keySet().iterator();i.hasNext();)
	   {
		   keyName = i.next();
		  // System.out.println("===> Key Name: "+keyName) ;
		   contextKey = htKeyTree.get(keyName);
		   		 
		   for(Iterator<IndContext> j =contextKey.keySet().iterator();j.hasNext();)
		   {
		       indCont = (IndContext) j.next();
			  // System.out.println("===> Context position: "+indCont.toString()) ; 
			   for(Iterator<TargetUpd> l =((Vector<TargetUpd>) contextKey.get(indCont)).iterator();l.hasNext();)
			   {
					 tUpd = (TargetUpd) l.next();
					System.out.println("  "+tUpd.toString());
			   }
		   }			 
	   }
	 }
	 
	 public Hashtable<String, Hashtable<IndContext, Vector<TargetUpd>>> getHtKeyTree()
	 {
	 	 return htKeyTree;
	 }	
}

